<?php

class H3OpenApiClient {
    private $baseUrl;
    private $appCode;
    private $appSecret;
    private $debug;
    private $token;
    private $tokenExpireTime;

    public function __construct($config) {
        $this->baseUrl = $config['baseUrl'];
        $this->appCode = $config['appCode'];
        $this->appSecret = $config['appSecret'];
        $this->debug = $config['debug'] ?? false;
        $this->token = null;
        $this->tokenExpireTime = 0;
    }

    public function loadBizObjects($schemaCode, $filter) {
        if (empty($schemaCode)) {
            throw new Exception("Schema code cannot be empty");
        }

        // 构建请求数据 - 按照参考文件的完整结构
        $data = [
            'ActionName' => 'LoadBizObjects',
            'SchemaCode' => $schemaCode,
            'Filter' => json_encode([
                'FromRowNum' => $filter['FromRowNum'] ?? 0,
                'ToRowNum' => $filter['ToRowNum'] ?? 500,
                'RequireCount' => $filter['RequireCount'] ?? true,
                'ReturnItems' => $filter['ReturnItems'] ?? [],
                'SortByCollection' => $filter['SortByCollection'] ?? [
                    [
                        'ItemName' => 'CreatedTime',
                        'Direction' => 'Descending'
                    ]
                ],
                'Matcher' => $filter['Matcher'] ?? [
                    'Type' => 'And',
                    'Matchers' => []
                ]
            ])
        ];

        // 获取业务对象数据
        $result = $this->sendRequest($data);
        if (!isset($result['ReturnData']['BizObjectArray']) || empty($result['ReturnData']['BizObjectArray'])) {
            return [];
        }

        return $result['ReturnData']['BizObjectArray'];
    }

    /**
     * 获取表单元数据（字段定义）
     */
    public function getBizSchema($schemaCode) {
        if (empty($schemaCode)) {
            throw new Exception("Schema code cannot be empty");
        }

        $data = [
            'ActionName' => 'GetBizSchema',
            'SchemaCode' => $schemaCode
        ];

        try {
            $result = $this->sendRequest($data);
            if (isset($result['ReturnData']['Schema'])) {
                return $result['ReturnData']['Schema'];
            } else {
                // 如果没有返回 schema，尝试从数据中推断字段
                return $this->inferSchemaFromData($schemaCode);
            }
        } catch (Exception $e) {
            // 日志已禁用
            // if ($this->debug) {
            //     $logDir = __DIR__ . '/../logs/api';
            //     if (!is_dir($logDir)) {
            //         mkdir($logDir, 0755, true);
            //     }
            //     $logFile = $logDir . '/api_debug.log';
            //     $timestamp = date('Y-m-d H:i:s');
            //     file_put_contents($logFile, "[{$timestamp}] 获取表单元数据失败，尝试从数据推断: {$e->getMessage()}\n", FILE_APPEND | LOCK_EX);
            // }
            return $this->inferSchemaFromData($schemaCode);
        }
    }

    /**
     * 从实际数据中推断字段定义
     */
    private function inferSchemaFromData($schemaCode) {
        try {
            // 获取一小部分数据用于分析字段
            $sampleData = $this->loadBizObjects($schemaCode, [
                'FromRowNum' => 0,
                'ToRowNum' => 5
            ]);
            
            if (empty($sampleData)) {
                return null;
            }
            
            $fields = [];
            $firstRecord = $sampleData[0];
            
            foreach ($firstRecord as $fieldCode => $value) {
                $fields[] = [
                    'Name' => $fieldCode,
                    'DisplayName' => $this->guessFieldDisplayName($fieldCode, $value),
                    'DataType' => $this->guessFieldDataType($value)
                ];
            }
            
            return [
                'Code' => $schemaCode,
                'Items' => $fields
            ];
            
        } catch (Exception $e) {
            // 日志已禁用
            // if ($this->debug) {
            //     $logDir = __DIR__ . '/../logs/api';
            //     if (!is_dir($logDir)) {
            //         mkdir($logDir, 0755, true);
            //     }
            //     $logFile = $logDir . '/api_debug.log';
            //     $timestamp = date('Y-m-d H:i:s');
            //     file_put_contents($logFile, "[{$timestamp}] 从数据推断字段失败: {$e->getMessage()}\n", FILE_APPEND | LOCK_EX);
            // }
            return null;
        }
    }
    
    /**
     * 猜测字段显示名称
     */
    private function guessFieldDisplayName($fieldCode, $value) {
        // 先检查是否是中文值，如果是中文可能就是显示名
        if (is_string($value) && preg_match('/[\x{4e00}-\x{9fa5}]/u', $value) && mb_strlen($value) < 50) {
            // 但是排除明显不是名称的值（如日期、ID等）
            if (!preg_match('/\d{4}[\/-]\d{1,2}[\/-]\d{1,2}/', $value) && 
                !preg_match('/^[a-f0-9\-]{36}$/i', $value)) {
                return $value; // 使用中文值作为显示名
            }
        }
        
        // 否则使用字段代码
        return $fieldCode;
    }
    
    /**
     * 猜测字段数据类型
     */
    private function guessFieldDataType($value) {
        if (is_null($value)) return 'String';
        if (is_bool($value)) return 'Boolean';
        if (is_int($value)) return 'Int';
        if (is_float($value)) return 'Decimal';
        if (is_array($value) || is_object($value)) return 'Object';
        
        if (is_string($value)) {
            if (preg_match('/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}/', $value)) {
                return 'DateTime';
            }
        }
        
        return 'String';
    }

    /**
     * 测试认证
     */
    public function testAuth() {
        try {
            // 读取配置文件获取动态表单编码
            $config = include dirname(__DIR__) . '/config.php';
            $schemaCode = $config['schema_code'] ?? '';
            
            if (empty($schemaCode)) {
                throw new Exception('配置文件中未找到schema_code');
            }
            
            $data = [
                'ActionName' => 'LoadBizObjects',
                'SchemaCode' => $schemaCode,
                'Filter' => json_encode([
                    'FromRowNum' => 0,
                    'ToRowNum' => 1,
                    'RequireCount' => true,
                    'ReturnItems' => [],
                    'SortByCollection' => [
                        [
                            'ItemName' => 'CreatedTime',
                            'Direction' => 'Descending'
                        ]
                    ],
                    'Matcher' => [
                        'Type' => 'And',
                        'Matchers' => []
                    ]
                ])
            ];
            
            $result = $this->sendRequest($data);
            return ['success' => true, 'message' => '认证成功'];
        } catch (Exception $e) {
            return ['success' => false, 'message' => '认证失败: ' . $e->getMessage()];
        }
    }

    /**
     * 测试连接
     */
    public function testConnection() {
        try {
            // 读取配置文件获取动态表单编码
            $config = include dirname(__DIR__) . '/config.php';
            $schemaCode = $config['schema_code'] ?? '';
            
            if (empty($schemaCode)) {
                throw new Exception('配置文件中未找到schema_code');
            }
            
            $data = [
                'ActionName' => 'LoadBizObjects',
                'SchemaCode' => $schemaCode,
                'Filter' => json_encode([
                    'FromRowNum' => 0,
                    'ToRowNum' => 1,
                    'RequireCount' => true,
                    'ReturnItems' => [],
                    'SortByCollection' => [
                        [
                            'ItemName' => 'CreatedTime',
                            'Direction' => 'Descending'
                        ]
                    ],
                    'Matcher' => [
                        'Type' => 'And',
                        'Matchers' => []
                    ]
                ])
            ];
            
            $this->sendRequest($data);
            return ['success' => true, 'message' => '连接成功'];
        } catch (Exception $e) {
            return ['success' => false, 'message' => '连接失败: ' . $e->getMessage()];
        }
    }

    private function sendRequest($data) {
        $headers = [
            'Content-Type: application/json',
            'EngineCode: ' . $this->appCode,
            'EngineSecret: ' . $this->appSecret
        ];

        // 日志已禁用
        // if ($this->debug) {
        //     $logDir = __DIR__ . '/../logs/api';
        //     if (!is_dir($logDir)) {
        //         mkdir($logDir, 0755, true);
        //     }
        //     $logFile = $logDir . '/api_debug.log';
        //     $timestamp = date('Y-m-d H:i:s');
        //     file_put_contents($logFile, "[{$timestamp}] Request URL: {$this->baseUrl}\n", FILE_APPEND | LOCK_EX);
        //     file_put_contents($logFile, "[{$timestamp}] Request Data: " . json_encode($data, JSON_UNESCAPED_UNICODE) . "\n", FILE_APPEND | LOCK_EX);
        // }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->baseUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        // 日志已禁用
        // if ($this->debug) {
        //     $logDir = __DIR__ . '/../logs/api';
        //     if (!is_dir($logDir)) {
        //         mkdir($logDir, 0755, true);
        //     }
        //     $logFile = $logDir . '/api_debug.log';
        //     $timestamp = date('Y-m-d H:i:s');
        //     file_put_contents($logFile, "[{$timestamp}] Response Code: {$httpCode}\n", FILE_APPEND | LOCK_EX);
        //     file_put_contents($logFile, "[{$timestamp}] Response Body: {$response}\n", FILE_APPEND | LOCK_EX);
        // }

        if ($response === false) {
            $error = curl_error($ch);
            curl_close($ch);
            throw new Exception("cURL Error: " . $error);
        }

        curl_close($ch);

        $result = json_decode($response, true);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception("Invalid JSON response: " . $response);
        }

        if (!isset($result['Successful']) || !$result['Successful']) {
            throw new Exception("API Error: " . ($result['ErrorMessage'] ?? $response));
        }

        return $result;
    }
}
?>